/*
 * 智能夜灯 + 信息仪表（最小可用版）
 * 依赖：
 *  - qu__dong/OLED 以 PB8/PB9 软件I2C 驱动 SSD1306
 *  - qu__dong/Buzzer 以 PB12 低电平有源蜂鸣器
 *  - qu__dong/LightSensor 以 PB13 数字光敏输入（上拉）
 *  - console = uart1
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#include <finsh.h>
#include <stdlib.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "qu__dong/OLED/OLED.h"
#include "qu__dong/Buzzer/Buzzer.h"
#include "qu__dong/LightSensor/LightSensor.h"
#if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
#include <drivers/adc.h>
#endif
#include <drv_common.h>

/* 可选：夜灯指示 LED 引脚，默认 PC13（常见板载 LED，低电平点亮） */
#ifndef NIGHT_LED_PIN
#define NIGHT_LED_PIN   GET_PIN(C, 13)
#endif

static volatile rt_uint8_t g_auto_mode = 1;      /* 1=自动控制蜂鸣器/LED */
static volatile rt_uint8_t g_invert_logic = 1;   /* 数字输入时代码保留；ADC 方案下无效 */
static volatile rt_uint8_t g_buzzer_enabled = 0; /* 1=蜂鸣器当前使能 */
static volatile rt_uint8_t g_light_dark = 0;     /* 1=暗，0=亮（逻辑态，已考虑反相） */
static volatile rt_uint16_t g_adc_thresh = 2000; /* ADC 阈值（0~4095），低于阈值判定为暗 */
static volatile rt_uint8_t  g_adc_channel = 0;   /* 默认 PA0=ADC1_IN0 */
#if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
static rt_adc_device_t g_adc = RT_NULL;
#else
static void *g_adc = RT_NULL; /* 无 ADC 框架时占位 */
#endif

/* 无滤波版：固定阈值比较 */

static void buzzer_set(rt_uint8_t on)
{
    if (on)
    {
        Buzzer_ON();
        g_buzzer_enabled = 1;
    }
    else
    {
        Buzzer_OFF();
        g_buzzer_enabled = 0;
    }
}

static void night_led_set(rt_uint8_t on)
{
    /* PC13 通常低电平点亮，这里按常见板载 LED 处理 */
    rt_pin_write(NIGHT_LED_PIN, on ? PIN_LOW : PIN_HIGH);
}

/* 采样线程：读取数字光敏输入，形成逻辑“暗/亮” */
static void sensor_thread_entry(void *parameter)
{
    const rt_tick_t period_ms = 100;
    (void)parameter;
    while (1)
    {
        if (g_adc)
        {
            #if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
            rt_uint32_t sum = 0;
            for (int i = 0; i < 8; i++)
            {
                sum += rt_adc_read(g_adc, g_adc_channel);
            }
            rt_uint16_t avg = (rt_uint16_t)(sum / 8);
            g_light_dark = (avg < g_adc_thresh) ? 1 : 0;
            #endif
        }
        else
        {
            rt_uint8_t raw = LightSensor_Get();
            rt_uint8_t val = g_invert_logic ? (raw ? 0 : 1) : (raw ? 1 : 0);
            g_light_dark = val;
        }
        rt_thread_mdelay(period_ms);
    }
}

/* 控制线程：基于光照状态驱动蜂鸣器与夜灯 LED，带简单防抖/迟滞（时间窗阈值） */
static void control_thread_entry(void *parameter)
{
    (void)parameter;
    const rt_uint32_t dark_hold_ms = 400;  /* 连续暗 >= 400ms 判定为暗 */
    const rt_uint32_t bright_hold_ms = 600;/* 连续亮 >= 600ms 判定为亮 */
    rt_tick_t dark_elapsed = 0, bright_elapsed = 0;
    rt_uint8_t state_dark = 0; /* 最终判定态 */

    while (1)
    {
        if (g_light_dark)
        {
            dark_elapsed += 100;
            bright_elapsed = 0;
            if (!state_dark && dark_elapsed >= dark_hold_ms)
            {
                state_dark = 1;
                if (g_auto_mode)
                {
                    night_led_set(1);
                    /* 进入黑暗时短促提示音 */
                    buzzer_set(1);
                    rt_thread_mdelay(80);
                    buzzer_set(0);
                }
            }
        }
        else
        {
            bright_elapsed += 100;
            dark_elapsed = 0;
            if (state_dark && bright_elapsed >= bright_hold_ms)
            {
                state_dark = 0;
                if (g_auto_mode)
                {
                    night_led_set(0);
                    /* 退出黑暗时双击提示 */
                    buzzer_set(1); rt_thread_mdelay(40);
                    buzzer_set(0); rt_thread_mdelay(40);
                    buzzer_set(1); rt_thread_mdelay(40);
                    buzzer_set(0);
                }
            }
        }

        /* 自动模式维持蜂鸣器关闭（除提示音外） */
        if (g_auto_mode && g_buzzer_enabled)
        {
            buzzer_set(0);
        }

        rt_thread_mdelay(100);
    }
}

/* UI 线程：OLED 显示状态 */
static void ui_thread_entry(void *parameter)
{
    (void)parameter;
    OLED_Init();
    OLED_Clear();
    OLED_ShowString(0, 0, "NightLight v1", OLED_6X8);
    OLED_Update();
    rt_thread_mdelay(300);

    while (1)
    {
        char line1[24];
        char line2[20];
        char line3[24];
        if (g_adc)
        {
            #if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
            rt_uint32_t v = rt_adc_read(g_adc, g_adc_channel);
            rt_snprintf(line1, sizeof(line1), "ADC :%4lu<%4u %s", v, g_adc_thresh,
                        (g_light_dark ? "DARK" : "BRIG"));
            #endif
        }
        else
        {
            rt_snprintf(line1, sizeof(line1), "Light:%s", g_light_dark ? "DARK" : "BRIG");
        }
        rt_snprintf(line2, sizeof(line2), "Auto :%s", g_auto_mode ? "ON" : "OFF");
        rt_snprintf(line3, sizeof(line3), "Buzz :%s", g_buzzer_enabled ? "ON" : "OFF");

        OLED_Clear();
        OLED_ShowString(0, 0,  "NightLight v1", OLED_6X8);
        OLED_ShowString(0, 8,  line1,        OLED_6X8);
        OLED_ShowString(0, 16, line2,        OLED_6X8);
        OLED_ShowString(0, 24, line3,        OLED_6X8);
        OLED_Update();

        rt_thread_mdelay(500);
    }
}

/* MSH 命令区 */
static int cmd_night_auto(int argc, char **argv)
{
    if (argc == 1)
    {
        rt_kprintf("auto=%d\n", g_auto_mode);
        return 0;
    }
    if (argc >= 2)
    {
        int v = atoi(argv[1]);
        g_auto_mode = (v ? 1 : 0);
        if (g_auto_mode == 0)
        {
            night_led_set(0);
            buzzer_set(0);
        }
        rt_kprintf("auto<=%d\n", g_auto_mode);
    }
    return 0;
}
MSH_CMD_EXPORT(cmd_night_auto, night_auto [0/1] 查看或设定自动控制);
MSH_CMD_EXPORT_ALIAS(cmd_night_auto, night_auto, night_auto [0/1] 查看或设定自动控制);

static int cmd_night_inv(int argc, char **argv)
{
    if (argc == 1)
    {
        rt_kprintf("invert=%d\n", g_invert_logic);
        return 0;
    }
    if (argc >= 2)
    {
        int v = atoi(argv[1]);
        g_invert_logic = (v ? 1 : 0);
        rt_kprintf("invert<=%d\n", g_invert_logic);
    }
    return 0;
}
MSH_CMD_EXPORT(cmd_night_inv, night_inv [0/1] 传感器取反设置);
MSH_CMD_EXPORT_ALIAS(cmd_night_inv, night_inv, night_inv [0/1] 传感器取反设置);

static int cmd_buz(int argc, char **argv)
{
    if (argc == 1)
    {
        rt_kprintf("buzz=%d\n", g_buzzer_enabled);
        return 0;
    }
    if (!rt_strcmp(argv[1], "1") || !rt_strcmp(argv[1], "on"))
    {
        g_auto_mode = 0; /* 手动控制时关闭自动模式，避免被复位 */
        buzzer_set(1);
    }
    else if (!rt_strcmp(argv[1], "0") || !rt_strcmp(argv[1], "off"))
    {
        buzzer_set(0);
    }
    else if (!rt_strcmp(argv[1], "tog"))
    {
        g_auto_mode = 0;
        buzzer_set(g_buzzer_enabled ? 0 : 1);
    }
    else if (!rt_strcmp(argv[1], "pulse"))
    {
        buzzer_set(1); rt_thread_mdelay(80); buzzer_set(0);
    }
    else
    {
        rt_kprintf("usage: buz [0|1|on|off|tog|pulse]\n");
    }
    return 0;
}
MSH_CMD_EXPORT(cmd_buz, buz [0/1/on/off/tog/pulse] 控制蜂鸣器);
MSH_CMD_EXPORT_ALIAS(cmd_buz, buz, buz [0/1/on/off/tog/pulse] 控制蜂鸣器);

static int cmd_night_state(int argc, char **argv)
{
    (void)argc; (void)argv;
    if (g_adc)
    {
        #if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
        rt_kprintf("adc=%lu ch=%u thr=%u dark=%d auto=%d buzz=%d\n",
                   rt_adc_read(g_adc, g_adc_channel), g_adc_channel, g_adc_thresh,
                   g_light_dark, g_auto_mode, g_buzzer_enabled);
        #else
        rt_kprintf("dark=%d auto=%d buzz=%d\n", g_light_dark, g_auto_mode, g_buzzer_enabled);
        #endif
    }
    else
    {
        rt_kprintf("light=%d(dark=%d) auto=%d buzz=%d inv=%d\n",
                   LightSensor_Get(), g_light_dark, g_auto_mode, g_buzzer_enabled, g_invert_logic);
    }
    return 0;
}
MSH_CMD_EXPORT(cmd_night_state, night_state 显示当前状态);
MSH_CMD_EXPORT_ALIAS(cmd_night_state, night_state, night_state 显示当前状态);

static int cmd_night_thr(int argc, char **argv)
{
    if (argc == 1)
    {
        rt_kprintf("thr=%u ch=%u\n", g_adc_thresh, g_adc_channel);
        return 0;
    }
    if (argc >= 2)
    {
        int v = atoi(argv[1]);
        if (v < 0) v = 0; if (v > 4095) v = 4095;
        g_adc_thresh = (rt_uint16_t)v;
    }
    if (argc >= 3)
    {
        int ch = atoi(argv[2]);
        if (ch >= 0 && ch <= 15) g_adc_channel = (rt_uint8_t)ch;
    }
    rt_kprintf("thr<=%u ch<=%u\n", g_adc_thresh, g_adc_channel);
    return 0;
}
MSH_CMD_EXPORT(cmd_night_thr, night_thr [thr] [ch] 设置/查看 ADC 阈值与通道);
MSH_CMD_EXPORT_ALIAS(cmd_night_thr, night_thr, night_thr [thr] [ch] 设置/查看 ADC 阈值与通道);

static void app_init_peripherals(void)
{
    /* 外设初始化：蜂鸣器、光敏、夜灯 LED */
    Buzzer_Init();
    /* 若使用 ADC 方案，尝试打开 adc1 设备；否则退回数字输入方案 */
    #if defined(RT_USING_ADC) && defined(BSP_USING_ADC1)
    g_adc = (rt_adc_device_t)rt_device_find("adc1");
    if (g_adc)
    {
        rt_adc_enable(g_adc, g_adc_channel);
    }
    else
    {
        LightSensor_Init();
    }
    #else
    LightSensor_Init();
    #endif
    rt_pin_mode(NIGHT_LED_PIN, PIN_MODE_OUTPUT);
    night_led_set(0);
}

static void start_threads(void)
{
    rt_thread_t th;

    th = rt_thread_create("sensor", sensor_thread_entry, RT_NULL, 1024, 15, 10);
    if (th) rt_thread_startup(th);

    th = rt_thread_create("ctrl", control_thread_entry, RT_NULL, 1024, 14, 10);
    if (th) rt_thread_startup(th);

    th = rt_thread_create("ui", ui_thread_entry, RT_NULL, 1536, 16, 10);
    if (th) rt_thread_startup(th);
}

int main(void)
{
    LOG_I("NightLight starting...");
    app_init_peripherals();

    /* 上电提示音 */
    buzzer_set(1); rt_thread_mdelay(60); buzzer_set(0);

    start_threads();

    /* 主线程保持存活，可用于后台日志 */
    while (1)
    {
        rt_thread_mdelay(1000);
    }

    /* unreachable */
    /* return RT_EOK; */
}
